﻿/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1
 *
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific language governing rights and limitations
 * under the License.
 *
 * The Original Code is tyzoh.jp code.
 *
 * The Initial Developer of the Original Code is Kazutaka Kurihara.
 * Portions created by the Initial Developer are Copyright (C) 2007
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * ***** END LICENSE BLOCK ***** */
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;

namespace ShuttleControl
{
	/// <summary>
	/// UserControl1 の概要の説明です。
	/// </summary>
	public class RShuttleControl : System.Windows.Forms.UserControl
	{
        private Bitmap bmTab;
		private int x = 0,y = 0;
		private int centerX,centerY;
		private int radius_E= 50;
		private int radius_M= 20;
		private double degree= 0;
		private double degreePre = 0;
		private double degreeVel= 0;
		private double degreeIntg = 0;
		private Color color = Color.White;
		private bool inDrag = false;

		public double Value
		{
			get{return degreeIntg/2/Math.PI;}
		}
		private double degreeAccum=0;
		public double AccumValue
		{
			get{return (degreeAccum+degreeIntg)/2/Math.PI;}
		}
		public void ResetAccumValue()
		{
			degreeAccum=0;
		}
		private int ticksPerRound = 1;
		public int TicksPerRound
		{
			get{return ticksPerRound;}
			set{ticksPerRound = value;}
		}
		private int tickPre = 0;

		public event EventHandler OnShuttleMove;
		public event EventHandler OnShuttleTickBack;
		public event EventHandler OnShuttleTickFwd;

        public event MouseEventHandler OnMouseMoveNotShuttle;
        public event MouseEventHandler OnMouseDownNotShuttle;
        public event MouseEventHandler OnMouseUpNotShuttle;

		/// <summary>
		/// 必要なデザイナ変数です。
		/// </summary>
		private System.ComponentModel.Container components = null;

		public RShuttleControl()
		{
			// この呼び出しは、Windows.Forms フォーム デザイナで必要です。
			InitializeComponent();

            bmTab = global::ShuttleControl.Properties.Resources.roll_handle;
		}

		/// <summary>
		/// 使用されているリソースに後処理を実行します。
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if( components != null )
					components.Dispose();
			}
			base.Dispose( disposing );
		}

		#region Component Designer generated code
		/// <summary>
		/// デザイナ サポートに必要なメソッドです。このメソッドの内容を 
		/// コード］エディタで変更しないでください。
		/// </summary>
		private void InitializeComponent()
		{
            this.SuspendLayout();
            // 
            // RShuttleControl
            // 
            this.BackColor = System.Drawing.Color.Transparent;
            this.BackgroundImage = global::ShuttleControl.Properties.Resources.stop_roller;
            this.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
            this.Cursor = System.Windows.Forms.Cursors.Hand;
            this.DoubleBuffered = true;
            this.Name = "RShuttleControl";
            this.Load += new System.EventHandler(this.UserControl1_Load);
            this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.ShuttleControl_MouseDown);
            this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.ShuttleControl_MouseMove);
            this.Resize += new System.EventHandler(this.ShuttleControl_Resize);
            this.Paint += new System.Windows.Forms.PaintEventHandler(this.UserControl1_Paint);
            this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.ShuttleControl_MouseUp);
            this.ResumeLayout(false);

		}
		#endregion

		private void UserControl1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
		{
			x = centerX + (int)(radius_E * Math.Sin(degree));
			y = centerY - (int)(radius_E * Math.Cos(degree));
            //e.Graphics.FillEllipse(new SolidBrush(Color.Black), centerX - 2, centerY - 2, 4, 4);

            //e.Graphics.DrawEllipse(Pens.Black,centerX-radius_E,centerY-radius_E,
            //    radius_E*2,radius_E*2);

            //e.Graphics.FillEllipse(new SolidBrush(color)
            //    ,x-radius_M
            //    ,y-radius_M
            //    ,radius_M*2
            //    ,radius_M*2);
            //e.Graphics.DrawEllipse(Pens.Black
            //    ,x-radius_M
            //    ,y-radius_M
            //    ,radius_M*2
            //    ,radius_M*2);

            e.Graphics.DrawImage(bmTab
				,x-radius_M
				,y-radius_M
				,radius_M*2
				,radius_M*2);
		}

        private static float offsetFactorX = 0.96f;
        private static float offsetFactorY = 0.96f;
        private void Init()
		{
			centerX = this.ClientRectangle.Left+(int)((float)this.ClientRectangle.Width/2f*offsetFactorX);
			centerY = this.ClientRectangle.Left+(int)((float)this.ClientRectangle.Height/2f*offsetFactorY);
			radius_E= this.ClientRectangle.Width/4;
			radius_M= this.ClientRectangle.Height/8;
		}
		private void UserControl1_Load(object sender, System.EventArgs e)
		{
			Init();
		}

		private void ShuttleControl_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
		{
            if (IsButtonDown(e.X, e.Y))
            {
                degreeIntg = 0;
                color = Color.WhiteSmoke;
                inDrag = true;
                this.Invalidate();
            }
            else
            {
                if (OnMouseDownNotShuttle != null) OnMouseDownNotShuttle(this, e);
            }
		}
		private int Distance(int x1,int y1,int x2,int y2)
		{
			return (int)(Math.Sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2)));
		}
		private bool IsButtonDown(int xx,int yy)
		{
			if (Distance(xx,yy,x,y) <= radius_M)
			{
				return true;
			}
			return false;
		}

		private void ShuttleControl_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
		{
			if (inDrag)
			{
				CalcDegree(e.X,e.Y);
				degreeIntg += degreeVel;
                if (degreeVel > 0)
                {
                    this.BackgroundImage = global::ShuttleControl.Properties.Resources.wide_roller;
                }
                else
                {
                    this.BackgroundImage = global::ShuttleControl.Properties.Resources.narrow_roller;
                }
				this.Invalidate();		

				int tickNow = (int)(this.Value * ticksPerRound);
				if (tickNow < tickPre && OnShuttleTickBack != null)
				{
					OnShuttleTickBack(this,new EventArgs());
				}
				if (tickNow > tickPre && OnShuttleTickFwd != null)
				{
					OnShuttleTickFwd(this,new EventArgs());
				}
				tickPre = tickNow;

				if (OnShuttleMove != null)
				{
					OnShuttleMove(this,new EventArgs());
				}

			}
            else
            {
                if (OnMouseMoveNotShuttle != null) OnMouseMoveNotShuttle(this, e);
            }

		}

		private void CalcDegree(int xx,int yy)
		{
			degreePre = degree;
			int ty = xx -centerX;
			int tx = centerY - yy;
			degree = Math.Atan2((double)ty,(double)tx);
			degreeVel = degree - degreePre;
			if(Math.Abs(degreeVel) > Math.PI/2) degreeVel = 0;
		}
		private void ShuttleControl_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
		{
            if (inDrag)
            {
                color = Color.White;
                inDrag = false;
                degreeAccum += degreeIntg;
                degreeIntg = 0;
                this.BackgroundImage = global::ShuttleControl.Properties.Resources.stop_roller;
                this.Invalidate();
            }
            else
            {
                if (OnMouseUpNotShuttle != null) OnMouseUpNotShuttle(this, e);
            }
		}

		private void ShuttleControl_Resize(object sender, System.EventArgs e)
		{
			Init();
			this.Invalidate();
		}
	}
}
